home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_360 / uucp / uucp0.lzh / src / uuser / uuser.c < prev    next >
C/C++ Source or Header  |  1990-05-17  |  14KB  |  548 lines

  1.  
  2. /*
  3.  *  UUSER.C UUSER:devicename/unitnumber/options
  4.  *        UUSER:serial.device/0/R1000
  5.  *
  6.  *  $Header: Beta:src/uucp/src/uuser/RCS/uuser.c,v 1.1 90/02/02 12:10:15 dillon Exp Locker: dillon $
  7.  *
  8.  *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
  9.  *
  10.  *  options:
  11.  *    Rn    Set read timeout when no data available to n millisecs
  12.  *    C0    Ignore carrier detect
  13.  *
  14.  *  features:
  15.  *    1K asynchronous write capability (write 0 bytes to sync up)
  16.  *    programmable read-timeout (Getty starts procs up w/ 1sec to)
  17.  *
  18.  *    combined together, you can easily implement 100% efficient
  19.  *    protocols even with that 1 second read timeout!
  20.  */
  21.  
  22. #include <exec/types.h>
  23. #include <exec/memory.h>
  24. #include <devices/serial.h>
  25. #include <devices/timer.h>
  26. #include <libraries/dos.h>
  27. #include <libraries/dosextens.h>
  28. #include <libraries/filehandler.h>
  29. #include <hardware/cia.h>
  30. #include <stdio.h>
  31. #include "protos.h"
  32. #include "version.h"
  33.  
  34. IDENT(".02");
  35.  
  36. #define WRITEBUFSIZE    1024
  37. #define MPC (MEMF_PUBLIC|MEMF_CLEAR)        /* options to AllocMem()    */
  38.  
  39. #define BTOC(x, type)   ((type *)((long)x << 2))
  40. #define CTOB(x)         ((BPTR)((long)x >> 2))
  41.  
  42. #define DOS_FALSE    0L
  43. #define DOS_TRUE     -1L
  44.  
  45. typedef struct IOExtSer     IOS;
  46. typedef struct timerequest  IOT;
  47. typedef struct IORequest    IOR;
  48. typedef struct timeval        TimeVal;
  49.  
  50. typedef struct FileLock     LOCK;
  51. typedef struct DosPacket    Packet;
  52. typedef struct Process        PROC;
  53. typedef struct DeviceNode   DEVNODE;
  54. typedef struct FileHandle   FH;
  55. typedef struct Message        MSG;
  56. typedef struct Node        NODE;
  57. typedef struct List        LIST;
  58. typedef struct MsgPort        PORT;
  59.  
  60. typedef struct SHandle {
  61.     NODE    Node;
  62.     IOT     Iot;        /* wait-for-char and read req    */
  63.     IOS     Ios;
  64.     IOS     Iosr;        /* 1005             */
  65.     IOS     Iosw;        /* 1005,1006            */
  66.     char    IotIP;
  67.     char    IosrIP;
  68.     char    IoswIP;
  69.     char    RxIn[1];        /* one char buffer        */
  70.     char    *TxOut;        /* asynch write buffer        */
  71.     Packet  *RPacket;        /* current pending read packet    */
  72.     Packet  *WPacket;        /* current pending write packet */
  73.     short   Flags;
  74.     LIST    RxWait;        /* requests waiting for data    */
  75.     LIST    TxWait;        /* requests waiting to write    */
  76.     LIST    CxWait;        /* wait for char        */
  77.     TimeVal ReadTo;
  78. } SHandle;
  79.  
  80. #define HF_IGNORECD    0x01
  81. #define HF_CDLOST    0x02
  82. #define HF_RTO        0x04
  83. #define HF_DONTLOCK    0x08    /* if G option for from-getty    */
  84.  
  85. extern Packet *taskwait();      /* wait for a message           */
  86.  
  87. /* long SysBase;        /* required to make Exec calls  */
  88. char ScrBuf[256];        /* Scratch buffer        */
  89. PORT *IoSink;
  90. LIST HanList;
  91. LIST NodList;
  92. IOT  Iot;            /* Iot master, also used for CD */
  93. char IotIP;
  94.  
  95. void    AttemptRead();
  96. void    AttemptWrite();
  97. void    AbortPackets();
  98. void    StartTimer();
  99.  
  100. void
  101. _main()
  102. {
  103.     PROC    *myproc;
  104.     DEVNODE    *mynode;
  105.     UBYTE    notdone;
  106.     long    mask;
  107.  
  108. /*    SysBase = *(long *)4;  */
  109.     IoSink = CreatePort(NULL, 0L);
  110.     NewList(&HanList);
  111.     NewList(&NodList);
  112.  
  113.     Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
  114.     OpenDevice("timer.device", UNIT_VBLANK, &Iot.tr_node, 0L);
  115.     Iot.tr_node.io_Command = TR_ADDREQUEST;
  116.     Iot.tr_time.tv_secs = 4;
  117.     Iot.tr_time.tv_micro= 0;
  118.     SendIO(&Iot);
  119.     IotIP = 1;
  120.  
  121.     myproc  = (PROC *)FindTask(0L);
  122.  
  123.     /*
  124.      * INITIAL STARTUP MESSAGE
  125.      */
  126.  
  127.     {
  128.     Packet *mypkt;
  129.  
  130.     mypkt    = taskwait(myproc);
  131.     mynode    = BTOC(mypkt->dp_Arg3, DEVNODE);
  132.     mynode->dn_Task = &myproc->pr_MsgPort;
  133.     returnpkt(mypkt, myproc, DOS_TRUE, 0L);
  134.     }
  135.  
  136. loop:
  137.     notdone = 1;
  138.     mask = (1 << IoSink->mp_SigBit) | (1 << myproc->pr_MsgPort.mp_SigBit);
  139.     while (notdone) {
  140.     Packet *mypkt;         /* dos packet received      */
  141.     IOR *ior;
  142.     SHandle *handle;
  143.     long type;            /* type of packet        */
  144.  
  145.     ior = (IOR *)GetMsg(IoSink);
  146.     mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
  147.     if (mypkt)
  148.         mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
  149.     while (mypkt == NULL && ior == NULL) {
  150.         Wait(mask);
  151.         ior = (IOR *)GetMsg(IoSink);
  152.         mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
  153.         if (mypkt)
  154.         mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
  155.     }
  156.  
  157.     /*
  158.      *  Make sure there is at least one free node in node list
  159.      */
  160.  
  161.     if (NodList.lh_Head == (NODE *)&NodList.lh_Tail) {
  162.         NODE *pknode = AllocMem(sizeof(NODE), MPC);
  163.         AddTail(&NodList, pknode);
  164.     }
  165.  
  166.     /*
  167.      *  Returned IO request, sift through lists to find it.
  168.      */
  169.  
  170.     if (ior) {
  171.         if (ior == &Iot.tr_node) {      /*  Check for carrier lost */
  172.         for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
  173.             if (!(handle->Flags & HF_IGNORECD) && !(handle->Flags & HF_CDLOST)) {
  174.             handle->Ios.IOSer.io_Command = SDCMD_QUERY;
  175.             DoIO((IOR *)&handle->Ios);
  176.             if (handle->Ios.io_Status & CIAF_COMCD) {
  177.                 handle->Flags |= HF_CDLOST;
  178.                 AbortPackets(handle, myproc);
  179.             }
  180.             }
  181.         }
  182.         if (HanList.lh_Head == (NODE *)&HanList.lh_Tail) {
  183.             IotIP = 0;
  184.         } else {
  185.             Iot.tr_time.tv_secs = 4;
  186.             Iot.tr_time.tv_micro= 0;
  187.             SendIO(&Iot.tr_node);
  188.             IotIP = 1;
  189.         }
  190.         } else
  191.         for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
  192.         if (ior == (IOR *)&handle->Iosr) {
  193.             handle->IosrIP = 0;
  194.             if (handle->RPacket) {
  195.             returnpkt(handle->RPacket, myproc, handle->Iosr.IOSer.io_Actual, 0L);
  196.             handle->RPacket = NULL;
  197.             }
  198.             if (handle->IotIP) {
  199.             AbortIO(&handle->Iot.tr_node);
  200.             WaitIO(&handle->Iot.tr_node);
  201.             handle->IotIP = 0;
  202.             }
  203.             AttemptRead(handle, myproc);
  204.         }
  205.         if (ior == (IOR *)&handle->Iosw) {
  206.             handle->IoswIP = 0;
  207.             if (handle->WPacket) {
  208.             handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
  209.             handle->Iosw.IOSer.io_Length= handle->WPacket->dp_Arg3 - handle->WPacket->dp_Res1;
  210.             SendIO((IOR *)&handle->Iosw);
  211.             handle->IoswIP = 1;
  212.             handle->WPacket->dp_Res1 = handle->WPacket->dp_Arg3;
  213.             returnpktplain(handle->WPacket, myproc);
  214.             handle->WPacket = NULL;
  215.             } else {
  216.             AttemptWrite(handle, myproc);
  217.             }
  218.         }
  219.         if (ior == (IOR *)&handle->Iot.tr_node) {
  220.             handle->IotIP = 0;
  221.             if ((handle->Flags & HF_RTO) && handle->IosrIP) {
  222.             AbortIO((IOR *)&handle->Iosr);
  223.             }
  224.         }
  225.         }
  226.     }
  227.  
  228.     if (mypkt) {
  229.         mypkt->dp_Res1 = DOS_TRUE;    /* default return value     */
  230.         mypkt->dp_Res2 = 0;     /* default no error        */
  231.         type = mypkt->dp_Type;    /* packet type            */
  232.  
  233.         /*
  234.          *    Extract pipe pointer (only applies to read/write)
  235.          */
  236.  
  237.         handle = (SHandle *)mypkt->dp_Arg1;     /*  READ/WRITE only */
  238.  
  239.         switch(type) {
  240.         case ACTION_FINDINPUT:
  241.         case ACTION_FINDOUTPUT:
  242.         case ACTION_FINDUPDATE:
  243.         if (IotIP == 0)
  244.             StartTimer(4);
  245.         {
  246.             FH     *fh = BTOC(mypkt->dp_Arg1, FH);
  247.             char *path = BTOC(mypkt->dp_Arg3, char);
  248.             char *unit;
  249.             long n;
  250.  
  251.             movmem(path + 1, ScrBuf, *path);
  252.             ScrBuf[*path] = 0;
  253.             path = ScrBuf;
  254.  
  255.             handle = AllocMem(sizeof(SHandle), MPC);
  256.  
  257.             if (strcmp(ScrBuf, "*") == 0)
  258.             strcpy(ScrBuf, "serial.device/0");
  259.             for (unit = path; *unit && *unit != '/'; ++unit) {
  260.             if (*unit == ':')
  261.                 path = unit + 1;
  262.             }
  263.             if (*unit == '/') {
  264.             char *opts;
  265.  
  266.             *unit = 0;
  267.             ++unit;
  268.             for (opts = unit; *opts && *opts != '/'; ++opts);
  269.             while (*opts) {
  270.                 n = atoi(opts + 1);
  271.                 switch(*opts) {
  272.                 case '/':
  273.                 break;
  274.                 case 'R':
  275.                 handle->ReadTo.tv_secs = n / 1000;
  276.                 handle->ReadTo.tv_micro= (n % 1000) * 1000;
  277.                 handle->Flags |= HF_RTO;
  278.                 break;
  279.                 case 'C':
  280.                 handle->Flags |= HF_IGNORECD;
  281.                 break;
  282.                 case 'G':
  283.                 if (n)
  284.                     handle->Flags |= HF_DONTLOCK;
  285.                 break;
  286.                 }
  287.                 ++opts;
  288.             }
  289.             }
  290.  
  291.             /* proc = (PROC *)mypkt->dp_Port->mp_SigTask; */
  292.  
  293.             /*
  294.              * Open the device
  295.              */
  296.  
  297.             handle->Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
  298.             handle->Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
  299.             if (OpenDevice(path, atoi(unit), (IOR *)&handle->Ios, 0L)) {
  300.             FreeMem(handle, sizeof(SHandle));
  301.             mypkt->dp_Res1 = DOS_FALSE;
  302.             mypkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
  303.             returnpktplain(mypkt, myproc);
  304.             break;
  305.             }
  306.             fh->fh_Arg1 = (long)handle;
  307.             fh->fh_Port = (struct MsgPort *)DOS_TRUE;
  308.  
  309.             handle->Iosr = handle->Ios;
  310.             handle->Iosw = handle->Ios;
  311.             handle->Iosr.IOSer.io_Command = CMD_READ;
  312.             handle->Iosw.IOSer.io_Command = CMD_WRITE;
  313.             handle->Iot = Iot;
  314.             NewList(&handle->RxWait);
  315.             NewList(&handle->TxWait);
  316.             NewList(&handle->CxWait);
  317.             AddTail(&HanList, &handle->Node);
  318.             returnpktplain(mypkt, myproc);
  319.         }
  320.         break;
  321.         case ACTION_END:
  322.         Remove(&handle->Node);
  323.         AbortPackets(handle, myproc);
  324.         if (handle->IotIP) {
  325.             AbortIO((IOR *)&handle->Iot);
  326.             WaitIO((IOR *)&handle->Iot);
  327.             handle->IotIP = 0;
  328.         }
  329.         CloseDevice((IOR *)&handle->Ios);
  330.         returnpktplain(mypkt, myproc);
  331.         if (handle->TxOut)
  332.             FreeMem(handle->TxOut, WRITEBUFSIZE);
  333.         FreeMem(handle, sizeof(SHandle));
  334.         break;
  335.         case ACTION_READ:
  336.         {
  337.             NODE *pknode = RemHead(&NodList);
  338.             mypkt->dp_Res1 = 0;
  339.             pknode->ln_Name = (char *)mypkt;
  340.             AddTail(&handle->RxWait, pknode);
  341.             AttemptRead(handle, myproc);
  342.         }
  343.         break;
  344.         case ACTION_WRITE:
  345.         {
  346.             NODE *pknode = RemHead(&NodList);
  347.             mypkt->dp_Res1 = 0;
  348.             pknode->ln_Name = (char *)mypkt;
  349.             AddTail(&handle->TxWait, pknode);
  350.             AttemptWrite(handle, myproc);
  351.         }
  352.         break;
  353.         case ACTION_WAIT_CHAR:
  354.         default:
  355.         returnpkt(mypkt, myproc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
  356.         break;
  357.         }
  358.     }
  359.     }
  360.  
  361.     /*
  362.      *    Can only exit if no messages pending.  There might be a window
  363.      *    here, but there is nothing that can be done about it.
  364.      */
  365.  
  366.     Forbid();
  367.     if (taskpktrdy(myproc)) {
  368.     Permit();
  369.     goto loop;
  370.     }
  371.     mynode->dn_Task = FALSE;
  372.     Permit();
  373.  
  374.     if (IotIP) {
  375.     AbortIO(&Iot.tr_node);
  376.     WaitIO(&Iot.tr_node);
  377.     }
  378.     CloseDevice(&Iot.tr_node);
  379.  
  380.     /* we are a process "so we fall off the end of the world" */
  381.     /* MUST fall through */
  382. }
  383.  
  384. void
  385. AttemptRead(handle, myproc)
  386. SHandle *handle;
  387. PROC *myproc;
  388. {
  389.     Packet *mypkt;
  390.     NODE *pknode;
  391.  
  392.     if (handle->Flags & HF_CDLOST) {
  393.     AbortPackets(handle, myproc);
  394.     return;
  395.     }
  396. loop:
  397.     if (handle->IosrIP == 0 && (pknode = RemHead(&handle->RxWait))) {
  398.     long n;
  399.  
  400.     AddTail(&NodList, pknode);
  401.  
  402.     mypkt = (Packet *)pknode->ln_Name;
  403.  
  404.     /*
  405.      *  special case.  If you read 0 bytes, 0 is returned if data
  406.      *  is pending, else -1, and NO timeout occurs.
  407.      */
  408.  
  409.     handle->Ios.IOSer.io_Command = SDCMD_QUERY;
  410.     DoIO((IOR *)&handle->Ios);
  411.  
  412.     if (mypkt->dp_Arg3 == 0) {
  413.         if (handle->Ios.IOSer.io_Actual > 0)
  414.         returnpkt(mypkt, myproc, DOS_FALSE, 0L);     /* 0=data rdy */
  415.         else
  416.         returnpkt(mypkt, myproc, DOS_TRUE, 0L);    /* -1=data not rdy */
  417.         goto loop;
  418.     }
  419.  
  420.     if ((n = handle->Ios.IOSer.io_Actual) > 0) {
  421.         if (n > mypkt->dp_Arg3)
  422.         n = mypkt->dp_Arg3;
  423.         handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
  424.         handle->Iosr.IOSer.io_Length = n;
  425.         DoIO((IOR *)&handle->Iosr);
  426.         mypkt->dp_Res1 = handle->Iosr.IOSer.io_Actual;
  427.         returnpktplain(mypkt, myproc);
  428.         goto loop;
  429.     }
  430.     handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
  431.     handle->Iosr.IOSer.io_Length = 1;
  432.     SendIO((IOR *)&handle->Iosr);
  433.     handle->IosrIP = 1;
  434.     handle->RPacket = mypkt;
  435.  
  436.     if (handle->Flags & HF_RTO) {
  437.         if (handle->IotIP) {
  438.         AbortIO(&handle->Iot.tr_node);
  439.         WaitIO(&handle->Iot.tr_node);
  440.         }
  441.         handle->Iot.tr_time = handle->ReadTo;
  442.         SendIO(&handle->Iot.tr_node);
  443.         handle->IotIP = 1;
  444.     }
  445.     }
  446. }
  447.  
  448. void
  449. AttemptWrite(handle, myproc)
  450. SHandle *handle;
  451. PROC *myproc;
  452. {
  453.     Packet *mypkt;
  454.     NODE *pknode;
  455.  
  456.     if (handle->Flags & HF_CDLOST) {
  457.     AbortPackets(handle, myproc);
  458.     return;
  459.     }
  460.     if (handle->IoswIP == 0 && (pknode = RemHead(&handle->TxWait))) {
  461.     AddTail(&NodList, pknode);
  462.  
  463.     mypkt = (Packet *)pknode->ln_Name;
  464.  
  465.     if (handle->TxOut == NULL)
  466.         handle->TxOut = AllocMem(WRITEBUFSIZE, MPC);
  467.  
  468.     if (mypkt->dp_Arg3 <= WRITEBUFSIZE) {   /* fully asynch */
  469.         movmem((char *)mypkt->dp_Arg2, handle->TxOut, mypkt->dp_Arg3);
  470.         handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
  471.         handle->Iosw.IOSer.io_Length = mypkt->dp_Arg3;
  472.         SendIO(&handle->Iosw);
  473.         mypkt->dp_Res1 = mypkt->dp_Arg3;
  474.         returnpktplain(mypkt, myproc);
  475.         handle->WPacket = NULL;
  476.     } else {                /*  semi-asynch */
  477.         long n = mypkt->dp_Arg3 - WRITEBUFSIZE;
  478.         handle->Iosw.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
  479.         handle->Iosw.IOSer.io_Length = n;
  480.         SendIO(&handle->Iosw);
  481.         movmem((char *)mypkt->dp_Arg2 + n, handle->TxOut, WRITEBUFSIZE);
  482.         mypkt->dp_Res1 += n;
  483.         handle->WPacket = mypkt;
  484.     }
  485.     handle->IoswIP = 1;
  486.     }
  487. }
  488.  
  489. void
  490. AbortPackets(handle, myproc)
  491. SHandle *handle;
  492. {
  493.     NODE *pknode;
  494.     Packet *mypkt;
  495.  
  496.     if (handle->RPacket)
  497.     returnpktplain(handle->RPacket, myproc);
  498.  
  499.     if (handle->WPacket)
  500.     returnpktplain(handle->WPacket, myproc);
  501.  
  502.     if (handle->IosrIP) {
  503.     AbortIO((IOR *)&handle->Iosr);
  504.     WaitIO((IOR *)&handle->Iosr);
  505.     handle->IosrIP = 0;
  506.     }
  507.     if (handle->IoswIP) {
  508.     AbortIO((IOR *)&handle->Iosw);
  509.     WaitIO((IOR *)&handle->Iosw);
  510.     handle->IoswIP = 0;
  511.     }
  512.  
  513.     handle->RPacket = NULL;
  514.     handle->WPacket = NULL;
  515.  
  516.     while (pknode = RemHead(&handle->RxWait)) {
  517.     mypkt = (Packet *)pknode->ln_Name;
  518.     if (mypkt->dp_Arg3 == 0)
  519.         mypkt->dp_Res1 = 0;     /* for poll, return data rdy */
  520.     else
  521.         mypkt->dp_Res1 = -1;
  522.     returnpktplain(mypkt, myproc);
  523.     AddTail(&NodList, pknode);
  524.     }
  525.  
  526.     while (pknode = RemHead(&handle->TxWait)) {
  527.     mypkt = (Packet *)pknode->ln_Name;
  528.     mypkt->dp_Res1 = -1;
  529.     returnpktplain(mypkt, myproc);
  530.     AddTail(&NodList, pknode);
  531.     }
  532. }
  533.  
  534. void
  535. StartTimer(secs)
  536. {
  537.     if (IotIP) {
  538.     AbortIO(&Iot.tr_node);
  539.     WaitIO(&Iot.tr_node);
  540.     }
  541.     Iot.tr_time.tv_secs = secs;
  542.     Iot.tr_time.tv_micro= 0;
  543.     SendIO(&Iot.tr_node);
  544.     IotIP = 1;
  545. }
  546.  
  547.  
  548.